package com.eagle.functioninterface;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * {@link java.util.function.Predicate} 函数式接口可以看成 {@link java.util.function.Function} 接口的一种
 * 特殊情况。 Function 是 x -> y 而 Predicate是x -> boolean ,
 * 当y= boolean时 Function 接口 就是Predicate接口
 *
 * @author qinlinsen
 */
public class PredicateTest5 {

    @Test
    public void testPredicateFilter() {
        List<Integer> sourceList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 12);
        //筛选出大于3的List
        List<Integer> result = filter(sourceList, x -> x > 3);
        System.out.println(String.format("result=%s", result));
        //筛选出是偶数的List
        List<Integer> anotherResult = filter(sourceList, x -> x % 2 == 0);
        System.out.println(result);
        System.out.println(String.format("anotherResult=%s", anotherResult));
    }


    @Test
    public void testFunctionFilter() {
        List<Integer> sourceList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 12);
        //筛选出大于3的List
        List<Integer> result = filter2(sourceList, x -> x > 3);
        System.out.println(String.format("result=%s", result));
        //筛选出是偶数的List
        List<Integer> anotherResult = filter2(sourceList, x -> x % 2 == 0);
        System.out.println(result);
        System.out.println(String.format("anotherResult=%s", anotherResult));
    }


    @Test
    public void testAnd() {
        Predicate<String> conditionOne = x -> x.startsWith("h");
        Predicate<String> conditionTwo = x -> x.endsWith("o");
        final boolean result = conditionOne.and(conditionTwo).test("hello");
        final boolean result2 = conditionOne.negate().and(conditionTwo).test("ello");
        System.out.println(result);
        System.out.println(result2);
    }


    @Test
    public void testNegate() {
        Predicate<String> conditionOne = x -> x.startsWith("h");
        final boolean result = conditionOne.negate().test("owe");
        System.out.println(result);
    }


    @Test
    public void testOr(){
        Predicate<String> conditionOne = x -> x.startsWith("h");
        Predicate<String> conditionTwo = x -> x.endsWith("o");
        final boolean result = conditionOne.or(conditionTwo).test("hell3");
        System.out.println(result);
    }


    private static <T> List<T> filter(List<T> sourceList, Predicate<T> condition) {
        Objects.requireNonNull(condition);
        List<T> result = new ArrayList<>();
        for (T item : sourceList) {
            if (condition.test(item)) {
                result.add(item);
            }
        }
        return result;
    }

    private static <T> List<T> filter2(List<T> sourceList, Function<T, Boolean> condition) {
        Objects.requireNonNull(condition);
        List<T> result = new ArrayList<>();
        for (T item : sourceList) {
            if (condition.apply(item)) {
                result.add(item);
            }
        }
        return result;
    }
}
